package netStudy;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 34255
 * Date: 2024-11-16
 * Time: 8:54
 */
public class TCPEchoServe {
    //创建TCP协议编程套接字Socket
    private ServerSocket serverSocket = null;

    public TCPEchoServe(int port) throws IOException {
        //为服务端套接字Socket绑定固定端口号
        serverSocket = new ServerSocket(port);
    }

    //启动服务器
    public void start() throws IOException {
        System.out.println("服务器启动");
        //由于不知道什么时候客户端会进行连接，且会发送多少请求
        ExecutorService executorService = Executors.newCachedThreadPool();
        while (true) {
            //由于TCP协议是有面向连接的，双方通信前需要先建立连接
            Socket clientSocket = serverSocket.accept();

//            //让主线程处理只处理accept()，每当accept()到一个连接，就创建一个线程来处理该连接的请求
//            Thread thread = new Thread(() -> {
//                HandlingRequests(clientSocket);
//            });
//            thread.start();

            //提交任务到阻塞队列中
            executorService.submit(()->{
                HandlingRequests(clientSocket);
            });
        }
    }

    private void HandlingRequests(Socket clientSocket) {
        System.out.println("客户端上线：" + clientSocket.getInetAddress() + " " + clientSocket.getPort());
        try (InputStream inputStream = clientSocket.getInputStream();
             OutputStream outputStream = clientSocket.getOutputStream();
             //对InputStream进行封装，通过Scanner来获取字节内容
             Scanner scanner = new Scanner(inputStream);
             //对OutputStreamPrintWriter进行封装，通过PrintWriter来打印字节内容
             PrintWriter printWriter = new PrintWriter(outputStream)) {

             while (true) {

                //还会判断读取到的数据中是否包含空白字符，没有的话会阻塞等待
                if (!scanner.hasNext()) {
                    System.out.println("客户端下线：" + clientSocket.getInetAddress() + " " + clientSocket.getPort());
                    break;
                }

                //1.读取请求并解析
                String requests = scanner.next();

                //2.处理请求计算响应
                String response = EchoSever(requests);

                //3.返回响应
                printWriter.println(response);
                //这里不使用/n会造成阻塞，数据会发送到通信对面，但是由于.next的作用，如果数据中不包含空白字符就会一直阻塞

                //由于网络IO的速度会比较慢，如果每次请求都进行一次IO，效率会比较慢，所以会等到数据先放置到
                //缓冲区内，等到数据量足够时，再一次新读取到内存中
                //刷新缓冲区
                printWriter.flush();

                //4.打印日志
                System.out.println("客户端IP：" + clientSocket.getInetAddress() + "端口号：" + clientSocket.getPort() + " 响应内容：" + response);

            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally{
            try {
                //每一个clientSocket对象对应一个连接，当连接执行完就需要把clientSocket资源关闭，避免资源泄露
                clientSocket.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    //回显响应
    private String EchoSever(String str){
        return str;
    }

    public static void main(String[] args) throws IOException {
        TCPEchoServe serve = new TCPEchoServe(9000);
        serve.start();

    }
}
